using System;
using System.Collections;
using System.Html;
using System.Runtime.CompilerServices;
using System.Serialization;
using ThemeChain;
using jQueryApi;

namespace Nsb.Classes
{
    [IgnoreNamespace]
    public static class Exceptions
    {
        public const string IsLoggedTxt = " (LOGGED=true)";
        public const string MissingAwaitDoneEr = "Missing Await Done Callback";
        public const string MissingDomElement = "Missing Dom Element";
        public const string ArgumentNull = "Argument Null";
        public const string NullReference = "Null Reference";
        public const string RecordNotExists = "Record doesn't exist";
        public const string NewRecordExists = "Record already exists";
        public const string InvalidName = "Invalid Name";
        public const string UserCancelled = "User Cancelled";
        public const string BlobLoadError = "Blob Load Error";
        public const string BlobSaveError = "Blob Save Error";
        public const string ServiceLoginFailure = "Service Login Failure";
        public const string FileIsNewer = "File is newer";
        public const string NewUser = "New User";
        public const string InvalidPageException = "Invalid Top Level Page";
        public const string SendMailError = "Send Mail Error";
        public const string InvalidTestCaseName = "Invalid Test Case Name";
        public const string InvalidTestSuiteName = "Invalid Test Suite Name";
        public const string InvalidDataOperation = "Invalid Database Operation";
        public const string NotImplementedExceptionString = "Not Implimented";

        public static object NullReferenceException
        {
            get
            {
                throw new Exception(NullReference);
            }
        }

        public static Exception NotImplementedException()
        {
            return new Exception(NotImplementedExceptionString);
        }

        public static string Format(string ex, string msg)
        {
            return ex + " : " + msg;
        }

        public static string Fn(object args)
        {
            return (string) Script.Literal("{0}.callee.name", args) ?? "unknown";
        }

        public static Exception Error(string exname, string msg, object fnargs)
        {
            if ((bool)Storage.GetLocal("DevStopOnError"))
                Script.Literal("debugger");
            string fnm = "";
            if (Type.GetScriptType(fnargs) == "string")
                fnm = (fnargs ?? "anonymous") + "() ";
            else if (Type.GetScriptType(fnargs) == "object")
                fnm = fnargs != null ? (((string)Script.Literal("{0}.callee.name", fnargs)) ?? "anonymous") + "() " : "";
            string ot = "";
            Exception ex = new Exception(exname + ": " + msg + IsLoggedTxt);
            string[] trace = (string[])Script.Literal("printStackTrace({0})", new Dictionary("e", ex, "guess", true));
            if (trace.Length > 0 && trace[trace.Length - 1].IndexOf("XMLHttpRequest") == -1) // Don't print traces for XMLHttpRequest floaters because they are not usefull
            foreach (string line in trace)
            {
                ot += line + "\n";
            }
            msg = fnm + ex + (!String.IsNullOrEmpty(ot) ? "\n" + ot : "");
            Type.SetField(ex, "mylogged", true);
            Inform.RawError(msg);
            SaveLog(ThemeBase.ErrorLogName, msg);
            return ex;
        }

        public static Exception AjaxError(string exname, string msg, jQueryXmlHttpRequest request, string textStatus, Exception error, object fnargs)
        {
            if (textStatus != "error" && textStatus != request.StatusText)
                return Error(exname, String.Format("{0}: ({1}) {2} {3}", msg, request.Status, request.StatusText, textStatus), fnargs);
            return Error(exname, String.Format("{0}: ({1}) {2}", msg, request.Status, request.StatusText), fnargs);
        }

        public static void LogException(Exception ex, string msg)
        {
            if ((bool)Storage.GetLocal("DevStopOnError"))
                Script.Literal("debugger");
            if (!(bool)Type.GetField(ex, "mylogged") && ex.Message.IndexOf(IsLoggedTxt) == -1)
            {
                try
                {
                    if (msg.IndexOf(ex.ToString()) == -1)
                        msg = msg + " : " + ex;
                    Inform.Error(msg);
                    Type.SetField(ex, "mylogged", true);
                    msg += IsLoggedTxt;
                    SaveLog(ThemeBase.ErrorLogName, msg);
                    Type.SetField(ex, "message", msg);
                }
                catch
                {
                }
            }
        }

        [PreserveName, PreserveCase]
        public static void SaveLog(string log, string msg)
        {
            Date d = new Date();
            msg = Json.Stringify(
                new Dictionary(
                    "t", d.GetTime(),
                    "d", d.ToDateString() + " " + d.ToTimeString(),
                    "i", ThemeBase.UserId,
                    "e", ThemeBase.Email,
                    "u", Window.Location.Href,
                    "m", msg,
                    "b", Window.Navigator.UserAgent
                    ));
            Dictionary args = new Dictionary(
                "password", FileBlobBase.Password,
                "path", Uri.DbPath("logs"),
                "file", log + ".txt",
                "content", msg,
                "createPath", true,
                "createFile", true
                );

            jQueryAjaxOptions options = new jQueryAjaxOptions();
            options.Url = Uri.App("file.app.php");
            options.DataType = "jsonp";
            options.Data = args;
            options.Type = "POST";

            options.Success =
                delegate { };

            options.Error =
                delegate { };
            jQuery.Ajax(options);
        }

        //public static Exception NotImplementedException
        //{
        //    get { return new Exception(NotImplementedExceptionString); }
        //}
    }
}